package crmdna.client.participant;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.ObjectifyFilter;

import crmdna.client.contactdetail.ContactDetail.ContactDetailProp;
import crmdna.client.group.Group.GroupProp;
import crmdna.client.member.Member;
import crmdna.client.member.MemberCore.MemberProp;
import crmdna.client.participant.Participant.ParticipantProp;
import crmdna.client.practice.Practice;
import crmdna.client.practice.Practice.PracticeProp;
import crmdna.client.program.Program;
import crmdna.client.program.Program.ProgramProp;
import crmdna.client.programtype.ProgramType;
import crmdna.client.programtype.ProgramType.ProgramTypeProp;
import crmdna.client.teacher.Teacher;
import crmdna.client.teacher.Teacher.TeacherProp;
import crmdna.client.user.User;
import crmdna.client.user.User.Action;
import crmdna.client.user.User.ResourceType;
import crmdna.client.venue.Venue;
import crmdna.client.venue.Venue.VenueProp;
import crmdna.crmdna.Client;

public class ParticipantTest {
	
	private final LocalServiceTestHelper datastoreHelper =
		        new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
		        .setApplyAllHighRepJobPolicy());
	
	private final String client = "isha";
 	private final String invalidClient = "invalid";
 	private final String validUser = "valid@login.com";
 	private final String sgpUser = "sgpuser@login.com";
 	private final String klUser = "kluser@login.com";
 	
 	GroupProp sgp;
 	GroupProp kl;
 	
 	PracticeProp suryaNamaskar;
 	PracticeProp yogaAsanas;
 	PracticeProp shambhavi;
 	PracticeProp aumChanting;
 	PracticeProp ishaKriya;
 	
 	ProgramTypeProp innerEngineering7Day;
 	ProgramTypeProp suryaNamaskarAndAsanas;
 	ProgramTypeProp ishaKriyaTeacherLed;
 	 		
 	VenueProp giis;
 	VenueProp chaichee;
 	VenueProp gujarathiBhavan;
 	VenueProp yuhuaCC;
 	VenueProp woodlandsCC;
 	
 	TeacherProp tina;
 	TeacherProp thulasi;
 	TeacherProp muthu;
 	
 	ProgramProp ishaKriya18Aug2013;
 	ProgramProp ishaKriya25Aug2013;
 	
    @Before
    public void setUp() {
        datastoreHelper.setUp();  
        ObjectifyFilter.complete();
        
        Client.create(client);
                   	
        sgp = crmdna.client.group.Group.create(client, "Singapore", User.SUPER_USER);
        assertEquals(1, sgp.groupId);
        
        kl = crmdna.client.group.Group.create(client, "KL", User.SUPER_USER);
        assertEquals(2, kl.groupId);
       
        User.create(client, validUser, sgp.groupId, User.SUPER_USER);
        assertEquals(1, User.get(client, validUser).toProp().userId);
        
        User.create(client, sgpUser, sgp.groupId, User.SUPER_USER);
        assertEquals(2, User.get(client, sgpUser).toProp().userId);
        
        User.addOrDeletePrivilege(client, sgpUser, ResourceType.PROGRAM, sgp.groupId, 
        		Action.WRITE, true, User.SUPER_USER);
        
        User.create(client, klUser, kl.groupId, User.SUPER_USER);
        assertEquals(3, User.get(client, klUser).toProp().userId);
        
        User.addOrDeletePrivilege(client, klUser, ResourceType.PROGRAM, kl.groupId, 
        		Action.WRITE, true, User.SUPER_USER);
        
        suryaNamaskar = Practice.create(client, "Surya Namaskar", User.SUPER_USER);
        yogaAsanas = Practice.create(client, "Yoga Asanas", User.SUPER_USER);
        shambhavi = Practice.create(client, "Shambhavi", User.SUPER_USER);
        ishaKriya = Practice.create(client, "Isha Kriya", User.SUPER_USER);
        aumChanting = Practice.create(client, "Aum Chanting", User.SUPER_USER);
        
        Set<Long> practiceIds = new HashSet<Long>();
        practiceIds.add(shambhavi.practiceId);
        practiceIds.add(aumChanting.practiceId);
        innerEngineering7Day = ProgramType.create(client, "Inner Engineering 7 day", 
        		practiceIds, User.SUPER_USER);
        
        practiceIds.clear();
        practiceIds.add(suryaNamaskar.practiceId);
        practiceIds.add(yogaAsanas.practiceId);
        suryaNamaskarAndAsanas = ProgramType.create(client, "Hata Yoga (Surya Namaskar & Asanas)", 
        		practiceIds, User.SUPER_USER);
        
        practiceIds.clear();
        practiceIds.add(ishaKriya.practiceId);        
        ishaKriyaTeacherLed = ProgramType.create(client, "Isha Kriya", 
        		practiceIds, User.SUPER_USER);
        
        giis = Venue.create(client, "GIIS", "GIIS", sgp.groupId, User.SUPER_USER);
        chaichee = Venue.create(client, "Chai Chee", "Chai Chee", sgp.groupId, User.SUPER_USER);
        gujarathiBhavan = Venue.create(client, "Gujarathi Bhavan", 
        		"Gujarathi Bhavan", sgp.groupId, User.SUPER_USER);
        yuhuaCC = Venue.create(client, "Yuhua CC", "Yuhua CC", sgp.groupId, User.SUPER_USER);
        woodlandsCC = Venue.create(client, "Woodlands CC", "Woodlands CC", sgp.groupId, User.SUPER_USER);
        
        tina = Teacher.create(client, "tina@ishafoundation.org", sgp.groupId, User.SUPER_USER);
        thulasi = Teacher.create(client, "thulasidhar@gmail.com", sgp.groupId, User.SUPER_USER);
        muthu = Teacher.create(client, "muthu_sys@yahoo.com", sgp.groupId, User.SUPER_USER);
        
        ishaKriya18Aug2013 = Program.create(client, sgp.groupId, 
        		ishaKriyaTeacherLed.programTypeId, woodlandsCC.venueId, 
        		muthu.teacherId, 20130818, 20130818, 1, null, User.SUPER_USER);
        
        ishaKriya25Aug2013 = Program.create(client, sgp.groupId, 
        		ishaKriyaTeacherLed.programTypeId, woodlandsCC.venueId, 
        		muthu.teacherId, 20130825, 20130825, 1, null, User.SUPER_USER);   
    }

    @After
    public void tearDown() {       
    	ObjectifyFilter.complete();
        datastoreHelper.tearDown();
    }
    
    @Test
    public void createWithoutDuplicateCheckTest() {  
    	ContactDetailProp c = new ContactDetailProp();
    	c.email = "oasisram@gmail.com";
    	c.firstName = "Ramakrishnan";
    	
    	ParticipantProp prop = 
    		Participant.createWithoutDuplicateCheck(client, c, ishaKriya18Aug2013.programId, 
    				User.SUPER_USER);    	
    	
    	prop = Participant.safeGet(client, prop.participantId).toProp();
    	assertEquals(1, prop.participantId);
    	assertEquals("Ramakrishnan", prop.contactDetail.firstName);
    	assertEquals(null, prop.contactDetail.lastName);
    	assertEquals(null, prop.contactDetail.mobilePhone);
    	assertEquals(1, prop.memberId); //first member
    	assertEquals(ishaKriya18Aug2013.groupProp.groupId, prop.groupId);
    	assertEquals(ishaKriya18Aug2013.programId, prop.programId);
    	
    	//should be able to get the associated member
    	MemberProp memberProp = Member.safeGet(client, prop.memberId, User.SUPER_USER).toProp();
    	assertEquals(prop.memberId, memberProp.memberId);
    	assertEquals(prop.contactDetail.firstName, memberProp.contact.firstName);
    	assertEquals(null, memberProp.contact.lastName);
    	assertEquals("oasisram@gmail.com", memberProp.contact.email);
    	assertTrue(memberProp.programIds.contains(ishaKriya18Aug2013.programId));
    	assertTrue(memberProp.programTypeIds.contains(ishaKriyaTeacherLed.programTypeId));
    	assertTrue(memberProp.practiceIds.contains(ishaKriya.practiceId));
    	
    	//add the same person as participant for another program
    	prop = Participant.createWithoutDuplicateCheck(client, c, ishaKriya25Aug2013.programId, User.SUPER_USER);
    	//should be tagged to the same member
    	prop = Participant.safeGet(client, prop.participantId).toProp();
    	assertEquals(2, prop.participantId); //id should be sequence
    	assertEquals("Ramakrishnan", prop.contactDetail.firstName);
    	assertEquals(null, prop.contactDetail.lastName);
    	assertEquals(null, prop.contactDetail.mobilePhone);
    	assertEquals(1, prop.memberId); //same member
    	assertEquals(ishaKriya18Aug2013.groupProp.groupId, prop.groupId);
    	assertEquals(ishaKriya18Aug2013.programId, prop.programId);
    	
    	//add somebody else who has given the same email
    	c = new ContactDetailProp();
    	c.email = "oasisram@gmail.com";
    	c.firstName = "Hemamalini";
    	c.lastName = "Krishnamurthy";
    	prop = Participant.createWithoutDuplicateCheck(client, c, ishaKriya25Aug2013.programId, User.SUPER_USER);
    	assertEquals(3, prop.participantId); //id should be sequence
    	assertEquals("Hemamalini", prop.contactDetail.firstName);
    	assertEquals("Krishnamurthy", prop.contactDetail.lastName);
    	assertEquals(null, prop.contactDetail.mobilePhone);
    	//should be tagged to a different member
    	assertEquals(2, prop.memberId); //same member
    	
    	memberProp = Member.safeGet(client, prop.memberId, User.SUPER_USER).toProp();
    	assertEquals(prop.memberId, memberProp.memberId);
    	assertEquals(prop.contactDetail.firstName, memberProp.contact.firstName);    	
    	assertEquals("oasisram@gmail.com", memberProp.contact.email);
    	assertTrue(memberProp.programIds.contains(ishaKriya18Aug2013.programId));
    	assertTrue(memberProp.programTypeIds.contains(ishaKriyaTeacherLed.programTypeId));
    	assertTrue(memberProp.practiceIds.contains(ishaKriya.practiceId));
    	
    	//add same person with a typo in the name
    	c = new ContactDetailProp();
    	c.email = "oasisram@gmail.com";
    	c.firstName = "Ramkrishnan";
    	//should get linked to the same member
    	prop = Participant.createWithoutDuplicateCheck(client, c, ishaKriya25Aug2013.programId, 
    			User.SUPER_USER);
    	memberProp = Member.safeGet(client, prop.memberId, User.SUPER_USER).toProp();
    	assertEquals(prop.memberId, memberProp.memberId);
    	assertEquals(prop.contactDetail.firstName, memberProp.contact.firstName);    	
    	assertEquals("oasisram@gmail.com", memberProp.contact.email);
    	assertTrue(memberProp.programIds.contains(ishaKriya18Aug2013.programId));
    	assertTrue(memberProp.programTypeIds.contains(ishaKriyaTeacherLed.programTypeId));
    	assertTrue(memberProp.practiceIds.contains(ishaKriya.practiceId));
    	
    	
    	
    	assertTrue(false);
    }
    
    @Test
    public void getTest() {
    	assertEquals("force failure", true, false);
    }
    
    @Test
    public void safeGetTest() {   
    	assertTrue(false);    	
    }
    
    @Test
    public void updateTest() {     	
    	assertTrue(false);    	    	    	   
    }
    
    @Test
    public void getQSMatchesTest() {
    	assertTrue(false);
    }
    
    @Test
    public void bulkUploadTest() {
    	assertTrue(false);
    }
    
    @Test
    public void deleteTest() {
    	assertTrue(false);
    }
}
